serial port names (#755)
authortsteven4 <13596209+tsteven4@users.noreply.github.com>
Fri, 5 Nov 2021 17:17:45 +0000 (11:17 -0600)
committerGitHub <noreply@github.com>
Fri, 5 Nov 2021 17:17:45 +0000 (11:17 -0600)
* try qserialportinfo again.

* update docker images with qt serial port.

* enhance windows device text to match device manager on windows.

deprecated/gui/serial_mac.cc [new file with mode: 0644]
gui/CMakeLists.txt
gui/app.pro
gui/mainwindow.cc
gui/serial_mac.cc [deleted file]
gui/serial_unix.cc
gui/serial_win.cc
tools/Dockerfile_f32
tools/Dockerfile_f33
tools/Dockerfile_f34
tools/Dockerfile_focal

diff --git a/deprecated/gui/serial_mac.cc b/deprecated/gui/serial_mac.cc
new file mode 100644 (file)
index 0000000..69fa90b
--- /dev/null
@@ -0,0 +1,209 @@
+// Borrowed liberally (as allowed by license) from
+// http://developer.apple.com/samplecode/SerialPortSample/index.html
+// This really is a slash-and-burn; no attempt was to make it very "C++-like"
+
+// Apple's copyright blob:
+/*
+    Copyright:         © Copyright 2000-2005 Apple Computer, Inc. All rights reserved.
+
+    Disclaimer:                IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                                       ("Apple") in consideration of your agreement to the following terms, and your
+                                       use, installation, modification or redistribution of this Apple software
+                                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                                       please do not use, install, modify or redistribute this Apple software.
+
+                                       In consideration of your agreement to abide by the following terms, and subject
+                                       to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
+                                       copyrights in this original Apple software (the "Apple Software"), to use,
+                                       reproduce, modify and redistribute the Apple Software, with or without
+                                       modifications, in source and/or binary forms; provided that if you redistribute
+                                       the Apple Software in its entirety and without modifications, you must retain
+                                       this notice and the following text and disclaimers in all such redistributions of
+                                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                                       Apple Software without specific prior written permission from Apple.  Except as
+                                       expressly stated in this notice, no other rights or licenses, express or implied,
+                                       are granted by Apple herein, including but not limited to any patent rights that
+                                       may be infringed by your derivative works or by other works in which the Apple
+                                       Software may be incorporated.
+
+                                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                                       COMBINATION WITH YOUR PRODUCTS.
+
+                                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <paths.h>
+#include <termios.h>
+#include <sysexits.h>
+#include <sys/param.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <time.h>
+#include <AvailabilityMacros.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/serial/IOSerialKeys.h>
+#if defined(MAC_OS_X_VERSION_10_3) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3)
+#include <IOKit/serial/ioss.h>
+#endif
+#include <IOKit/IOBSD.h>
+
+#include "mainwindow.h"
+
+// Function prototypes
+static kern_return_t FindModems(io_iterator_t* matchingServices);
+// static kern_return_t GetModemPath(io_iterator_t serialPortIterator, char *bsdPath, CFIndex maxPathSize);
+// static int OpenSerialPort(const char *bsdPath);
+
+// Returns an iterator across all known modems. Caller is responsible for
+// releasing the iterator when iteration is complete.
+static kern_return_t FindModems(io_iterator_t* matchingServices)
+{
+  kern_return_t                        kernResult;
+  CFMutableDictionaryRef       classesToMatch;
+
+  /*! @function IOServiceMatching
+      @abstract Create a matching dictionary that specifies an IOService class match.
+      @discussion A very common matching criteria for IOService is based on its class. IOServiceMatching will create a matching dictionary that specifies any IOService of a class, or its subclasses. The class is specified by C-string name.
+      @param name The class name, as a const C-string. Class matching is successful on IOService's of this class or any subclass.
+      @result The matching dictionary created, is returned on success, or zero on failure. The dictionary is commonly passed to IOServiceGetMatchingServices or IOServiceAddNotification which will consume a reference, otherwise it should be released with CFRelease by the caller. */
+
+  // Serial devices are instances of class IOSerialBSDClient
+  classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
+  if (classesToMatch == NULL) {
+    printf("IOServiceMatching returned a NULL dictionary.\n");
+  } else {
+    /*!
+       @function CFDictionarySetValue
+       Sets the value of the key in the dictionary.
+       @param theDict The dictionary to which the value is to be set. If this
+               parameter is not a valid mutable CFDictionary, the behavior is
+               undefined. If the dictionary is a fixed-capacity dictionary and
+               it is full before this operation, and the key does not exist in
+               the dictionary, the behavior is undefined.
+       @param key The key of the value to set into the dictionary. If a key
+               which matches this key is already present in the dictionary, only
+               the value is changed ("add if absent, replace if present"). If
+               no key matches the given key, the key-value pair is added to the
+               dictionary. If added, the key is retained by the dictionary,
+               using the retain callback provided
+               when the dictionary was created. If the key is not of the sort
+               expected by the key retain callback, the behavior is undefined.
+       @param value The value to add to or replace into the dictionary. The value
+               is retained by the dictionary using the retain callback provided
+               when the dictionary was created, and the previous value if any is
+               released. If the value is not of the sort expected by the
+               retain or release callbacks, the behavior is undefined.
+    */
+//        CFDictionarySetValue(classesToMatch,
+//                             CFSTR(kIOSerialBSDTypeKey),
+//                             CFSTR(kIOSerialBSDModemType));
+
+    // Each serial device object has a property with key
+    // kIOSerialBSDTypeKey and a value that is one of kIOSerialBSDAllTypes,
+    // kIOSerialBSDModemType, or kIOSerialBSDRS232Type. You can experiment with the
+    // matching by changing the last parameter in the above call to CFDictionarySetValue.
+
+    // As shipped, this sample is only interested in modems,
+    // so add this property to the CFDictionary we're matching on.
+    // This will find devices that advertise themselves as modems,
+    // such as built-in and USB modems. However, this match won't find serial modems.
+  }
+
+  /*! @function IOServiceGetMatchingServices
+      @abstract Look up registered IOService objects that match a matching dictionary.
+      @discussion This is the preferred method of finding IOService objects currently registered by IOKit. IOServiceAddNotification can also supply this information and install a notification of new IOServices. The matching information used in the matching dictionary may vary depending on the class of service being looked up.
+      @param masterPort The master port obtained from IOMasterPort().
+      @param matching A CF dictionary containing matching information, of which one reference is consumed by this function. IOKitLib can contruct matching dictionaries for common criteria with helper functions such as IOServiceMatching, IOOpenFirmwarePathMatching.
+      @param existing An iterator handle is returned on success, and should be released by the caller when the iteration is finished.
+      @result A kern_return_t error code. */
+
+  kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, matchingServices);
+  if (KERN_SUCCESS != kernResult) {
+    printf("IOServiceGetMatchingServices returned %d\n", kernResult);
+    goto exit;
+  }
+
+exit:
+  return kernResult;
+}
+
+// Given an iterator across a set of modems, return the BSD path to the first one.
+// If no modems are found the path name is set to an empty string.
+static kern_return_t GetModemPath(io_iterator_t serialPortIterator, char* bsdPath, CFIndex maxPathSize, QComboBox* box)
+{
+  io_object_t          modemService;
+  kern_return_t        kernResult = KERN_FAILURE;
+  Boolean                      modemFound = false;
+
+  // Initialize the returned path
+  *bsdPath = '\0';
+
+  // Iterate across all modems found. In this example, we bail after finding the first modem.
+
+  while ((modemService = IOIteratorNext(serialPortIterator)) && !modemFound) {
+    CFTypeRef  bsdPathAsCFString;
+
+    // Get the callout device's path (/dev/cu.xxxxx). The callout device should almost always be
+    // used: the dialin device (/dev/tty.xxxxx) would be used when monitoring a serial port for
+    // incoming calls, e.g. a fax listener.
+
+    bsdPathAsCFString = IORegistryEntryCreateCFProperty(modemService,
+                        CFSTR(kIOCalloutDeviceKey),
+                        kCFAllocatorDefault,
+                        0);
+    if (bsdPathAsCFString) {
+      Boolean result;
+
+      // Convert the path from a CFString to a C (NUL-terminated) string for use
+      // with the POSIX open() call.
+
+      result = CFStringGetCString((const __CFString*) bsdPathAsCFString,
+                                  bsdPath,
+                                  maxPathSize,
+                                  kCFStringEncodingUTF8);
+      CFRelease(bsdPathAsCFString);
+
+      if (result) {
+        box->addItem(bsdPath);
+      }
+    }
+
+    // Release the io_service_t now that we are done with it.
+
+//             (void) IOObjectRelease(modemService);
+  }
+
+  return kernResult;
+}
+
+#include "mainwindow.h"
+void MainWindow::osLoadDeviceNameCombos(QComboBox* box)
+{
+  kern_return_t       kernResult;
+  io_iterator_t       serialPortIterator;
+  char                bsdPath[MAXPATHLEN];
+
+  kernResult = FindModems(&serialPortIterator);
+  kernResult = GetModemPath(serialPortIterator, bsdPath, sizeof(bsdPath), box);
+
+}
index 3d0c77b0e62242f277c9e12b26ce9fdef03fd1b0..d7515a067fe2c412023cbcfe7c85f709f8e75cc2 100644 (file)
@@ -21,8 +21,8 @@ set(CMAKE_AUTORCC ON)
 
 # Find the QtCore library
 find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
-find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Network Widgets Xml REQUIRED)
-list(APPEND QT_LIBRARIES Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Xml)
+find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Network SerialPort Widgets Xml REQUIRED)
+list(APPEND QT_LIBRARIES Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::SerialPort Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Xml)
 if(${Qt${QT_VERSION_MAJOR}Core_VERSION} VERSION_LESS 5.12)
   message(FATAL_ERROR "Qt version ${Qt${QT_VERSION_MAJOR}Core_VERSION} found, but version 5.12 or newer is required.")
 else()
@@ -32,19 +32,6 @@ endif()
 find_package(Qt${QT_VERSION_MAJOR} COMPONENTS WebEngineWidgets WebChannel REQUIRED)
 list(APPEND QT_LIBRARIES Qt${QT_VERSION_MAJOR}::WebEngineWidgets Qt${QT_VERSION_MAJOR}::WebChannel)
 
-if(APPLE)
-  find_library(IOKIT_LIBRARIES IOKit)
-  find_library(COREFOUNDATION_LIBRARIES CoreFoundation)
-endif()
-
-if(UNIX AND NOT APPLE)
-  find_package(PkgConfig REQUIRED)
-  pkg_check_modules(LIBUDEV libudev)
-  if(${LIBUDEV_FOUND})
-    add_definitions(-DHAVE_UDEV)
-  endif()
-endif()
-
 set(RESOURCES app.qrc)
 
 if(WIN32)
@@ -99,10 +86,8 @@ set(SOURCES
   version_mismatch.cc
 )
 
-if(UNIX AND NOT APPLE)
+if(UNIX)
   set(SOURCES ${SOURCES} serial_unix.cc)
-elseif(APPLE)
-  set(SOURCES ${SOURCES} serial_mac.cc)
 elseif(WIN32)
   set(SOURCES ${SOURCES} serial_win.cc)
 endif()
@@ -148,7 +133,7 @@ else()
   add_executable(${TARGET} ${SOURCES} ${HEADERS} ${RESOURCES})
 endif()
 
-set(LIBS ${QT_LIBRARIES} ${LIBUDEV_LIBRARIES} ${IOKIT_LIBRARIES} ${COREFOUNDATION_LIBRARIES})
+set(LIBS ${QT_LIBRARIES})
 list(REMOVE_DUPLICATES LIBS)
 target_link_libraries(${TARGET} ${LIBS})
 
index 66e804d6245142f565446c1d9a2874d9978c0958..d7bbd11d0b51829e35acaa8bc9f378ad313a97f5 100755 (executable)
@@ -12,6 +12,7 @@ ICON = images/appicon.icns
 QT += core \
       gui \
       network \
+      serialport \
       widgets \
       xml
 
@@ -27,15 +28,6 @@ unix:OBJECTS_DIR = objects
 unix:RCC_DIR = objects
 mac:DESTDIR = .
 
-mac:LIBS += -framework IOKit -framework CoreFoundation
-unix {
-    CONFIG += link_pkgconfig
-    packagesExist(libudev) {
-        DEFINES += HAVE_UDEV
-        PKGCONFIG += libudev
-    }
-}
-
 UI_DIR = tmp
 
 RESOURCES = app.qrc
@@ -95,10 +87,8 @@ SOURCES += processwait.cc
 SOURCES += runmachine.cc
 SOURCES += upgrade.cc
 SOURCES += version_mismatch.cc
-unix:!mac {
+unix {
   SOURCES += serial_unix.cc
-} else:mac {
-  SOURCES += serial_mac.cc
 } else:windows {
   SOURCES += serial_win.cc
 }
index 63b1a2400270c519d7453c6d7795cf8bf9c00b44..8ff9b058c66fdd0e6f77ede37434f8c438c2fed6 100644 (file)
@@ -1091,7 +1091,9 @@ void MainWindow::dropEvent(QDropEvent* event)
 void MainWindow::setComboToDevice(QComboBox* comboBox, const QString& name)
 {
   for (int i=0; i<comboBox->count(); i++) {
-    if (comboBox->itemText(i) == name) {
+    QString value = comboBox->itemData(i).isValid()?
+      comboBox->itemData(i).toString() : comboBox->itemText(i);
+    if (value == name) {
       comboBox->setCurrentIndex(i);
       break;
     }
@@ -1266,7 +1268,8 @@ void MainWindow::getWidgetValues()
     babelData_.inputType_ = BabelData::deviceType_;
     babelData_.inputDeviceFormat_ =formatList_[fidx].getName();
   }
-  babelData_.inputDeviceName_ = ui_.inputDeviceNameCombo->currentText();
+  babelData_.inputDeviceName_ = ui_.inputDeviceNameCombo->currentData().isValid()?
+    ui_.inputDeviceNameCombo->currentData().toString() : ui_.inputDeviceNameCombo->currentText();
 
   comboIdx = ui_.outputFormatCombo->currentIndex();
   fidx = ui_.outputFormatCombo->itemData(comboIdx).toInt();
@@ -1279,7 +1282,8 @@ void MainWindow::getWidgetValues()
   } else {
     babelData_.outputType_ = BabelData::noType_;
   }
-  babelData_.outputDeviceName_ = ui_.outputDeviceNameCombo->currentText();
+  babelData_.outputDeviceName_ = ui_.outputDeviceNameCombo->currentData().isValid()?
+    ui_.outputDeviceNameCombo->currentData().toString() : ui_.outputDeviceNameCombo->currentText();
 
   babelData_.xlateWayPts_ = ui_.xlateWayPtsCk->isChecked();
   babelData_.xlateTracks_ = ui_.xlateTracksCk->isChecked();
diff --git a/gui/serial_mac.cc b/gui/serial_mac.cc
deleted file mode 100644 (file)
index 69fa90b..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-// Borrowed liberally (as allowed by license) from
-// http://developer.apple.com/samplecode/SerialPortSample/index.html
-// This really is a slash-and-burn; no attempt was to make it very "C++-like"
-
-// Apple's copyright blob:
-/*
-    Copyright:         © Copyright 2000-2005 Apple Computer, Inc. All rights reserved.
-
-    Disclaimer:                IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
-                                       ("Apple") in consideration of your agreement to the following terms, and your
-                                       use, installation, modification or redistribution of this Apple software
-                                       constitutes acceptance of these terms.  If you do not agree with these terms,
-                                       please do not use, install, modify or redistribute this Apple software.
-
-                                       In consideration of your agreement to abide by the following terms, and subject
-                                       to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
-                                       copyrights in this original Apple software (the "Apple Software"), to use,
-                                       reproduce, modify and redistribute the Apple Software, with or without
-                                       modifications, in source and/or binary forms; provided that if you redistribute
-                                       the Apple Software in its entirety and without modifications, you must retain
-                                       this notice and the following text and disclaimers in all such redistributions of
-                                       the Apple Software.  Neither the name, trademarks, service marks or logos of
-                                       Apple Computer, Inc. may be used to endorse or promote products derived from the
-                                       Apple Software without specific prior written permission from Apple.  Except as
-                                       expressly stated in this notice, no other rights or licenses, express or implied,
-                                       are granted by Apple herein, including but not limited to any patent rights that
-                                       may be infringed by your derivative works or by other works in which the Apple
-                                       Software may be incorporated.
-
-                                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
-                                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
-                                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-                                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
-                                       COMBINATION WITH YOUR PRODUCTS.
-
-                                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
-                                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-                                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-                                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
-                                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
-                                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
-                                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-*/
-
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <paths.h>
-#include <termios.h>
-#include <sysexits.h>
-#include <sys/param.h>
-#include <sys/select.h>
-#include <sys/time.h>
-#include <time.h>
-#include <AvailabilityMacros.h>
-
-#include <CoreFoundation/CoreFoundation.h>
-
-#include <IOKit/IOKitLib.h>
-#include <IOKit/serial/IOSerialKeys.h>
-#if defined(MAC_OS_X_VERSION_10_3) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3)
-#include <IOKit/serial/ioss.h>
-#endif
-#include <IOKit/IOBSD.h>
-
-#include "mainwindow.h"
-
-// Function prototypes
-static kern_return_t FindModems(io_iterator_t* matchingServices);
-// static kern_return_t GetModemPath(io_iterator_t serialPortIterator, char *bsdPath, CFIndex maxPathSize);
-// static int OpenSerialPort(const char *bsdPath);
-
-// Returns an iterator across all known modems. Caller is responsible for
-// releasing the iterator when iteration is complete.
-static kern_return_t FindModems(io_iterator_t* matchingServices)
-{
-  kern_return_t                        kernResult;
-  CFMutableDictionaryRef       classesToMatch;
-
-  /*! @function IOServiceMatching
-      @abstract Create a matching dictionary that specifies an IOService class match.
-      @discussion A very common matching criteria for IOService is based on its class. IOServiceMatching will create a matching dictionary that specifies any IOService of a class, or its subclasses. The class is specified by C-string name.
-      @param name The class name, as a const C-string. Class matching is successful on IOService's of this class or any subclass.
-      @result The matching dictionary created, is returned on success, or zero on failure. The dictionary is commonly passed to IOServiceGetMatchingServices or IOServiceAddNotification which will consume a reference, otherwise it should be released with CFRelease by the caller. */
-
-  // Serial devices are instances of class IOSerialBSDClient
-  classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
-  if (classesToMatch == NULL) {
-    printf("IOServiceMatching returned a NULL dictionary.\n");
-  } else {
-    /*!
-       @function CFDictionarySetValue
-       Sets the value of the key in the dictionary.
-       @param theDict The dictionary to which the value is to be set. If this
-               parameter is not a valid mutable CFDictionary, the behavior is
-               undefined. If the dictionary is a fixed-capacity dictionary and
-               it is full before this operation, and the key does not exist in
-               the dictionary, the behavior is undefined.
-       @param key The key of the value to set into the dictionary. If a key
-               which matches this key is already present in the dictionary, only
-               the value is changed ("add if absent, replace if present"). If
-               no key matches the given key, the key-value pair is added to the
-               dictionary. If added, the key is retained by the dictionary,
-               using the retain callback provided
-               when the dictionary was created. If the key is not of the sort
-               expected by the key retain callback, the behavior is undefined.
-       @param value The value to add to or replace into the dictionary. The value
-               is retained by the dictionary using the retain callback provided
-               when the dictionary was created, and the previous value if any is
-               released. If the value is not of the sort expected by the
-               retain or release callbacks, the behavior is undefined.
-    */
-//        CFDictionarySetValue(classesToMatch,
-//                             CFSTR(kIOSerialBSDTypeKey),
-//                             CFSTR(kIOSerialBSDModemType));
-
-    // Each serial device object has a property with key
-    // kIOSerialBSDTypeKey and a value that is one of kIOSerialBSDAllTypes,
-    // kIOSerialBSDModemType, or kIOSerialBSDRS232Type. You can experiment with the
-    // matching by changing the last parameter in the above call to CFDictionarySetValue.
-
-    // As shipped, this sample is only interested in modems,
-    // so add this property to the CFDictionary we're matching on.
-    // This will find devices that advertise themselves as modems,
-    // such as built-in and USB modems. However, this match won't find serial modems.
-  }
-
-  /*! @function IOServiceGetMatchingServices
-      @abstract Look up registered IOService objects that match a matching dictionary.
-      @discussion This is the preferred method of finding IOService objects currently registered by IOKit. IOServiceAddNotification can also supply this information and install a notification of new IOServices. The matching information used in the matching dictionary may vary depending on the class of service being looked up.
-      @param masterPort The master port obtained from IOMasterPort().
-      @param matching A CF dictionary containing matching information, of which one reference is consumed by this function. IOKitLib can contruct matching dictionaries for common criteria with helper functions such as IOServiceMatching, IOOpenFirmwarePathMatching.
-      @param existing An iterator handle is returned on success, and should be released by the caller when the iteration is finished.
-      @result A kern_return_t error code. */
-
-  kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, matchingServices);
-  if (KERN_SUCCESS != kernResult) {
-    printf("IOServiceGetMatchingServices returned %d\n", kernResult);
-    goto exit;
-  }
-
-exit:
-  return kernResult;
-}
-
-// Given an iterator across a set of modems, return the BSD path to the first one.
-// If no modems are found the path name is set to an empty string.
-static kern_return_t GetModemPath(io_iterator_t serialPortIterator, char* bsdPath, CFIndex maxPathSize, QComboBox* box)
-{
-  io_object_t          modemService;
-  kern_return_t        kernResult = KERN_FAILURE;
-  Boolean                      modemFound = false;
-
-  // Initialize the returned path
-  *bsdPath = '\0';
-
-  // Iterate across all modems found. In this example, we bail after finding the first modem.
-
-  while ((modemService = IOIteratorNext(serialPortIterator)) && !modemFound) {
-    CFTypeRef  bsdPathAsCFString;
-
-    // Get the callout device's path (/dev/cu.xxxxx). The callout device should almost always be
-    // used: the dialin device (/dev/tty.xxxxx) would be used when monitoring a serial port for
-    // incoming calls, e.g. a fax listener.
-
-    bsdPathAsCFString = IORegistryEntryCreateCFProperty(modemService,
-                        CFSTR(kIOCalloutDeviceKey),
-                        kCFAllocatorDefault,
-                        0);
-    if (bsdPathAsCFString) {
-      Boolean result;
-
-      // Convert the path from a CFString to a C (NUL-terminated) string for use
-      // with the POSIX open() call.
-
-      result = CFStringGetCString((const __CFString*) bsdPathAsCFString,
-                                  bsdPath,
-                                  maxPathSize,
-                                  kCFStringEncodingUTF8);
-      CFRelease(bsdPathAsCFString);
-
-      if (result) {
-        box->addItem(bsdPath);
-      }
-    }
-
-    // Release the io_service_t now that we are done with it.
-
-//             (void) IOObjectRelease(modemService);
-  }
-
-  return kernResult;
-}
-
-#include "mainwindow.h"
-void MainWindow::osLoadDeviceNameCombos(QComboBox* box)
-{
-  kern_return_t       kernResult;
-  io_iterator_t       serialPortIterator;
-  char                bsdPath[MAXPATHLEN];
-
-  kernResult = FindModems(&serialPortIterator);
-  kernResult = GetModemPath(serialPortIterator, bsdPath, sizeof(bsdPath), box);
-
-}
index ce44710f5a5f4077bf945296b5e99429aca1e0de..05cbfd77aff73d55f15b53c2dd393a88f83136e4 100644 (file)
 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
 //  USA.
 //
-#include "mainwindow.h"
 
-#ifdef HAVE_UDEV
-#include <libudev.h>            // for udev_device_get_property_value, udev_device_get_devnode, udev_device_new_from_syspath, udev_device_unref, udev_enumerate_add_match_subsystem, udev_enumerate_get_list_entry, udev_enumerate_new, udev_enumerate_scan_devices, udev_enumerate_unref, udev_list_ent...
+#include <QComboBox>        // for QComboBox
+#include <QList>            // for QList
+#include <QSerialPortInfo>  // for QSerialPortInfo
 
-#include <QDebug>               // for QDebug
-#include <QSet>                 // for QSet
-#include <QString>              // for QString, operator==
-#include <QStringList>          // for QStringList
-#include <QComboBox>            // for QComboBox
+#include "mainwindow.h"     // for MainWindow
 
-#include "mainwindow.h"         // for MainWindow
-
-
-static QStringList dynamicDevices()
-{
-  struct udev* udev = udev_new();
-  if (!udev) {
-    qDebug() << "Can't create udev";
-    return QStringList();
-  }
-
-  QSet<QString> devices;
-
-  struct udev_enumerate* enumerate = udev_enumerate_new(udev);
-  udev_enumerate_add_match_subsystem(enumerate, "tty");
-  udev_enumerate_scan_devices(enumerate);
-
-  struct udev_list_entry* device;
-  udev_list_entry_foreach(device, udev_enumerate_get_list_entry(enumerate)) {
-    const char* path = udev_list_entry_get_name(device);
-    struct udev_device* dev = udev_device_new_from_syspath(udev, path);
-
-    bool okMaj;
-    bool okMin;
-    int major = QString(udev_device_get_property_value(dev, "MAJOR")).toInt(&okMaj);
-    int minor = QString(udev_device_get_property_value(dev, "MINOR")).toInt(&okMin);
-    if (!okMaj || !okMin) {
-      major = -1;
-      minor = -1;
-    }
-
-    // see Documentation/devices.txt in the linux tree
-    if (!((major == 4 || major == 5) && 0 <= minor && minor <= 63)) {
-      devices << QString::fromUtf8(udev_device_get_devnode(dev));
-      /*
-      udev_device_get_sysattr_list_entry(dev);
-      udev_device_get_tags_list_entry(dev);
-      struct udev_list_entry *prop;
-      qDebug() << "Device Node Path:" << udev_device_get_devnode(dev) << path;
-      udev_list_entry_foreach(prop, udev_device_get_properties_list_entry(dev)) {
-          qDebug() << "  " << udev_list_entry_get_name(prop)
-                   << "=>" << udev_list_entry_get_value(prop);
-      }
-      */
-    }
-    udev_device_unref(dev);
-  }
-  udev_enumerate_unref(enumerate);
-  udev_unref(udev);
-
-  QStringList list = devices.values();
-  list.sort();
-  return list;
-}
-#else
-static QStringList dynamicDevices()
-{
-  return QStringList();
-}
-#endif
-
-
-static const char* deviceNames[] = {
-  "/dev/ttyS0",
-  "/dev/ttyS1",
-  "/dev/ttyS2",
-  "/dev/ttyS3",
-  "/dev/ttyUSB0",
-  "/dev/rfcomm0",
-  nullptr
-};
 
 void MainWindow::osLoadDeviceNameCombos(QComboBox* box)
 {
-  const QStringList devices = dynamicDevices();
-  box->addItems(devices);
-
-  for (int i=0; deviceNames[i] != nullptr; i++) {
-    if (!devices.contains(deviceNames[i])) {
-      box->addItem(deviceNames[i]);
-    }
+  const auto ports = QSerialPortInfo::availablePorts();
+  for (const auto& info : ports) {
+    box->addItem(info.systemLocation());
   }
 }
index e4870775e205f71609681cf6c9aaaa02195e582e..3674289051c44cc95f1c3305eb330d1d84d42f18 100644 (file)
 //  USA.
 //
 
-#include "mainwindow.h"
+#include <QComboBox>        // for QComboBox
+#include <QList>            // for QList
+#include <QSerialPortInfo>  // for QSerialPortInfo
 
-#if 0  // Does not require Windows 2000
+#include "mainwindow.h"     // for MainWindow
 
-static const char* deviceNames[] = {
-  "com1:",
-  "com2:",
-  "com3:",
-  "com4:",
-  0
-};
 
 void MainWindow::osLoadDeviceNameCombos(QComboBox* box)
 {
-  for (int i=0; deviceNames[i]; i++) {
-    box->addItem(deviceNames[i]);
-  }
-}
-
-#else // This code assumes Windows 2000 or later
-
-// Uses QueryDosDevice(), Minimum supported: Windows 2000 Professional/Server
-#include <windows.h>
-#include <stdio.h>
-
-void MainWindow::osLoadDeviceNameCombos(QComboBox* box)
-{
-  char DevList[64*1024-1];  // a single byte more, and certain versions of windows
-  // always return QueryDosDevice()==0 && GetLastError()==ERROR_MORE_DATA.
-  // see http://support.microsoft.com/kb/931305
-  // Get a list of all existing MS-DOS device names. Stores one or more ASCII strings followed by an extra null.
-  DWORD res = QueryDosDeviceA(NULL, DevList, sizeof(DevList));
-  if (res == 0) {
-    DWORD err = GetLastError(); // could check for ERROR_INSUFFICIENT_BUFFER, and retry with a larger buffer.
-    // but DevList is already at the maximum size it can be without running into kb 931305.
-    // FIXME: This should be a QMessageBox::warning() - RJL
-    // fprintf(stderr,"QueryDosDevice() failed with %d.  GetLastError()==%d.\n", res, err);
-    (void) err;
-    return;
-  }
-
-  for (char* p=DevList; *p;) {
-    int len = strlen(p);
-    if (strncmp(p,"COM",3)==0) {
-      box->addItem((PCHAR)p);
+  const auto ports = QSerialPortInfo::availablePorts();
+  for (const auto& info : ports) {
+    if (info.description().isEmpty()) {
+      box->addItem(info.portName());
+    } else {
+      box->addItem(QString("%1 (%2)").arg(info.description(), info.portName()), info.portName());
     }
-    p += len+1; // +1 to also skip the null character of each string
   }
 }
-
-#endif
index e21bcad4f5ba250451159fd36bcf43e87964e261..b77f242f8ea3cf9a81a461562e85f3b0953053c2 100644 (file)
@@ -13,7 +13,7 @@ RUN dnf install --assumeyes git make valgrind diffutils which findutils langpack
 RUN dnf install --assumeyes libusbx-devel zlib-devel shapelib-devel && \
     dnf clean all
 # Qt used by gpsbabel, gpsbabelfe
-RUN dnf install --assumeyes qt5-qtbase-devel qt5-qtwebengine-devel qt5-linguist qt5-qttranslations && \
+RUN dnf install --assumeyes qt5-qtbase-devel qt5-qtserialport-devel qt5-qtwebengine-devel qt5-linguist qt5-qttranslations && \
     dnf clean all
 # tools to build the docs
 RUN dnf install --assumeyes expat desktop-file-utils libxslt docbook-style-xsl fop && \
index d2637df7321af158ce071b8e575ff83960a915d1..75cf4f945b2c5d2acaddfb89184a414a755c88c2 100644 (file)
@@ -13,7 +13,7 @@ RUN dnf install --assumeyes git make valgrind diffutils which findutils langpack
 RUN dnf install --assumeyes libusbx-devel zlib-devel shapelib-devel && \
     dnf clean all
 # Qt used by gpsbabel, gpsbabelfe
-RUN dnf install --assumeyes qt5-qtbase-devel qt5-qtwebengine-devel qt5-linguist qt5-qttranslations && \
+RUN dnf install --assumeyes qt5-qtbase-devel qt5-qtserialport-devel qt5-qtwebengine-devel qt5-linguist qt5-qttranslations && \
     dnf clean all
 # tools to build the docs
 RUN dnf install --assumeyes expat desktop-file-utils libxslt docbook-style-xsl fop && \
index 69c1675d0e12beb7f1522b020c81c32020918d5b..54350eec6d97c3a3f0e5da6b928a25243d9b8e25 100644 (file)
@@ -13,7 +13,7 @@ RUN dnf install --assumeyes git make valgrind diffutils which findutils langpack
 RUN dnf install --assumeyes libusbx-devel zlib-devel shapelib-devel && \
     dnf clean all
 # Qt used by gpsbabel, gpsbabelfe
-RUN dnf install --assumeyes qt5-qtbase-devel qt5-qtwebengine-devel qt5-linguist qt5-qttranslations && \
+RUN dnf install --assumeyes qt5-qtbase-devel qt5-qtserialport-devel qt5-qtwebengine-devel qt5-linguist qt5-qttranslations && \
     dnf clean all
 # tools to build the docs
 RUN dnf install --assumeyes expat desktop-file-utils libxslt docbook-style-xsl fop && \
index 85d6187433826aa20ed6f8f5a6e3c61e5171cd96..b171d3d9b02ec2344fbbd0ac76a05d061fe890be 100644 (file)
@@ -57,6 +57,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
     qttools5-dev-tools \
     qttranslations5-l10n \
     qtwebengine5-dev \
+    libqt5serialport5-dev \
  && rm -rf /var/lib/apt/lists/*
 
 # pkgs needed to generate coverage report: